package com.mc.lp.database.dao.impl;

import java.sql.Blob;
import java.util.ArrayList;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.transform.Transformers;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Repository;

import com.mc.lp.database.dao.IAttachmentDAO;
import com.mc.lp.database.entity.AttachmentEntity;
import com.mc.lp.database.entity.type.RecordType;
import com.mc.lp.database.exception.ConcurrentAccessException;
import com.mc.lp.shared.vo.FileVo;
import com.mc.lp.shared.vo.SearchCriteriaVO;
/*
 * @author aphanda
 * @date Sep 29, 2014
 * @time 10:15:43 PM
 */


@Repository
public class AttachmentDAOImpl  extends
AbstractGenericHibernateDAO<AttachmentEntity, Long, IAttachmentDAO> implements
IAttachmentDAO {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
	public List<AttachmentEntity> fetchAttachments(SearchCriteriaVO criteria)
			throws DataAccessException {

		// AP wrong business applied, missing condition check for recordTypeId
		// to use recordId as primary identifier to fetch rows. 
		
		// DV Agreed!! please send recordId in the searchCriteria
		List<AttachmentEntity> attachmentList = new ArrayList<AttachmentEntity>();

		Criteria crit = this.getCurrentSession().createCriteria(AttachmentEntity.class);

		if (criteria.getStudentEntityId() != null)
			crit.add(Restrictions.eq("entityId.id", criteria.getStudentEntityId()));

		if (criteria.getRecordType() != null)
			crit.add(Restrictions.eq("recordTypeId", Integer.parseInt(criteria.getRecordType())));

		if (criteria.getYear() != null)
			crit.add(Restrictions.eq("year", Integer.parseInt(criteria.getYear())));
		

		crit.add(Restrictions.eq("termId", criteria.getTermId()));
		crit.add(Restrictions.eq("gradeId", criteria.getGradeId()));

		attachmentList = crit.list();
		return attachmentList;
	}

	@Override
	public void saveMultipleAttachments(List<AttachmentEntity> attachmentList) throws DataAccessException {
		for(AttachmentEntity entity: attachmentList){
			this.getCurrentSession().save(entity);
		}
	}

	@Override
	public void deleteAttachment(Long id) throws DataAccessException {
		try {
			this.deleteById(id);
		} catch (ConcurrentAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public AttachmentEntity fetchAttachment(SearchCriteriaVO criteria) throws DataAccessException {

		Criteria crit = this.getCurrentSession().createCriteria(AttachmentEntity.class);

		if (criteria.getStudentEntityId() != null)
			crit.add(Restrictions.eq("entityId.id", criteria.getStudentEntityId()));

		if (criteria.getRecordType() != null)
			crit.add(Restrictions.eq("recordTypeId", Integer.parseInt(criteria.getRecordType())));

		if (criteria.getYear() != null)
			crit.add(Restrictions.eq("year", Integer.parseInt(criteria.getYear())));

		crit.add(Restrictions.eq("termId", criteria.getTermId()));
		crit.add(Restrictions.eq("gradeId", criteria.getGradeId()));
		
		return (AttachmentEntity)crit.uniqueResult();
	}


	@Override
	public List<AttachmentEntity> fetchAttachmentWithoutData(SearchCriteriaVO criteria)
			throws DataAccessException {
		// 	to Fetch limited data by Projection
		Criteria cr = getCurrentSession().createCriteria(AttachmentEntity.class);
		getAttachmentWithoutDataCriteria(false, cr);
		
		if (criteria.getStudentEntityId() != null)
			cr.add(Restrictions.eq("entityId.id", criteria.getStudentEntityId()));
		if (criteria.getRecordType() != null)
			cr.add(Restrictions.eq("recordTypeId",(RecordType.getType(criteria.getRecordType()).getId())));
		if (criteria.getYear() != null)
			cr.add(Restrictions.eq("year", Integer.parseInt(criteria.getYear())));
		cr.add(Restrictions.eq("termId", criteria.getTermId()));
		cr.add(Restrictions.eq("gradeId", criteria.getGradeId()));
		List<AttachmentEntity> list = cr.list();

		return list;
	}

	@Override
	public AttachmentEntity saveAttachment(AttachmentEntity attachmentEntity, FileVo vo)
			throws DataAccessException {
		try {
			
			Blob data = this.getCurrentSession().getLobHelper().createBlob(vo.getData().getBytes());
			attachmentEntity.setData(data);
			
			return saveOrUpdate(attachmentEntity);
		} catch (ConcurrentAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public AttachmentEntity getAttachmentByRecordTypeAndIdentifiers(Long entityId, Long recordId,
			RecordType recordType) throws DataAccessException {
		Criteria crit = this.getCurrentSession().createCriteria(AttachmentEntity.class);

		if (entityId != null)
			crit.add(Restrictions.eq("entityId.id", entityId));

		if (recordId != null)
			crit.add(Restrictions.eq("recordId", recordId));

		crit.add(Restrictions.eq("recordTypeId", recordType.getId()));
		return (AttachmentEntity) crit.uniqueResult();
	}

	@Override
	public List<AttachmentEntity> fetchAttachmentsByGrade(Long entityId, Integer grade,
			RecordType recordType, boolean isDataRequired) throws DataAccessException {
	
		Criteria crit = this.getCurrentSession().createCriteria(AttachmentEntity.class);
		getAttachmentWithoutDataCriteria(isDataRequired, crit);

		if (entityId != null)
			crit.add(Restrictions.eq("entityId.id", entityId));

		if (grade != null)
			crit.add(Restrictions.eq("gradeId", grade));

		crit.add(Restrictions.eq("recordTypeId", recordType.getId()));
		
		return  (List<AttachmentEntity>)crit.list();
	}

	private void getAttachmentWithoutDataCriteria(boolean isDataRequired, Criteria crit) {
		if(!isDataRequired){
			crit.setProjection(Projections.projectionList()
					.add(Projections.property("id"), "id")
					.add(Projections.property("name"), "name"))
					.setResultTransformer(Transformers.aliasToBean(AttachmentEntity.class));
		}
	}
}
